/*
 * Copyright (C) 2004 Johan Maasing johan at zoom.nu Licensed under the Apache
 * License, Version 2.0 (the "License"); you may not use this file except in
 * compliance with the License. You may obtain a copy of the License at
 * http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law
 * or agreed to in writing, software distributed under the License is
 * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the specific language
 * governing permissions and limitations under the License.
 */
package nu.zoom.swing.table;

import javax.swing.table.*;
import javax.swing.event.*;
import java.util.*;

/**
 * A table model to present read-only strings.
 * 
 * @author $Author: johan $
 * @version $Revision: 1.2 $
 */
public class StringTableModel implements TableModel {

    protected Vector<TableModelListener> listeners = new Vector<TableModelListener>();
    ArrayList<ArrayList<Object>> columns;
    String[] headers;
    int currentColumn = 0;
    int numColumns = 0;

    /**
     * Create a new read only table model. Add entries to the table by calling
     * addEntry.
     *
     * @see #addEntry(String)
     * @param columnNames
     *            A string array with the column names (will be used for the
     *            column header). The length of the array determines how many
     *            columns the table will have. null is not a legal value and
     *            neither is an empty array.
     * @throws IllegalArgumentException
     *             if the number of columns is &lt; 1 or columnNames is null.
     */
    public StringTableModel(String[] columnNames)
            throws IllegalArgumentException {
        super();

        if (columnNames == null) {
            throw new IllegalArgumentException(
                    "StringTableModel can not be created with a null value for column names.");
        }
        numColumns = columnNames.length;
        if (numColumns < 1) {
            throw new IllegalArgumentException(
                    "StringTableModel can not be created with less than one column.");
        }
        headers = new String[numColumns];
        for (int n = 0; n < numColumns; n++) {
            headers[n] = new String(columnNames[n]);
        }
        clear();
    }

    /**
     * Fills up the table from left to right (and wrapping when end of row).
     */
    public void addEntry(String entry) {
        columns.get(currentColumn++).add(entry);
        if (currentColumn >= numColumns) {
            currentColumn = 0;
            fireTableChanged(new TableModelEvent(this));
        }
    }

    /**
     * Reset the table model and throw away all values. 
     */
    public void clear() {
        currentColumn = 0;
        columns = new ArrayList<ArrayList<Object>>();
        for (int n = 0; n < numColumns; n++) {
            columns.add(new ArrayList<Object>());
        }
        fireTableChanged(new TableModelEvent(this));
    }

    /*
     * (non-Javadoc)
     *
     * @see javax.swing.table.TableModel#getColumnClass(int)
     */
    @Override
    public Class<?> getColumnClass(int columnIndex) {
        return String.class;
    }

    @Override
    public int getColumnCount() {
        return numColumns;
    }

    @Override
    public String getColumnName(int columnIndex) {
        return headers[columnIndex];
    }

    @Override
    public int getRowCount() {
        return columns.get(0).size();
    }

    @Override
    public Object getValueAt(int rowIndex, int columnIndex) {
        try {
            return columns.get(columnIndex).get(rowIndex);
        } catch (ArrayIndexOutOfBoundsException exc) {
            return "";
        }
    }

    @Override
    public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
        columns.get(columnIndex).set(rowIndex, aValue);
    }

    @Override
    public boolean isCellEditable(int rowIndex, int columnIndex) {
        return false;
    }

    @Override
    public void addTableModelListener(TableModelListener l) {
        listeners.addElement(l);
    }

    @Override
    public void removeTableModelListener(TableModelListener l) {
        listeners.removeElement(l);
    }

    //
    // Utility methods for event notification
    //
    protected void fireTableChanged(TableModelEvent evt) {
        int s = listeners.size();
        for (int n = 0; n < s; n++) {
            ((TableModelListener) listeners.elementAt(n)).tableChanged(evt);
        }
    }

    protected void fireCellChanged(int column, int row) {
        TableModelEvent evt = new TableModelEvent(this, row, row, column);
        fireTableChanged(evt);
    }
}
